package ac.github.oa.internal.core.attribute.impl

import ac.github.oa.api.event.entity.EntityDamageEvent
import ac.github.oa.internal.base.event.EventMemory
import ac.github.oa.internal.base.event.impl.DamageMemory
import ac.github.oa.internal.core.attribute.*
import ac.github.oa.util.doDamage
import org.bukkit.entity.LivingEntity
import org.bukkit.event.entity.EntityDeathEvent
import taboolib.common.platform.event.SubscribeEvent
import taboolib.common.platform.function.info
import taboolib.common.platform.function.submit
import taboolib.common.platform.function.submitAsync
import taboolib.common.platform.service.PlatformExecutor
import taboolib.common.util.random
import taboolib.common5.Coerce
import java.util.Collections

object Fire : AbstractAttribute() {

    val map = Collections.synchronizedMap(mutableMapOf<LivingEntity,Data>())

    val org.bukkit.event.entity.EntityDamageEvent.isFire: Boolean
        get() = cause == org.bukkit.event.entity.EntityDamageEvent.DamageCause.FIRE || cause == org.bukkit.event.entity.EntityDamageEvent.DamageCause.FIRE_TICK

    @SubscribeEvent
    fun e(e: org.bukkit.event.entity.EntityDamageEvent) {
        if (e.isFire && map.containsKey(e.entity)) {
            e.damage = map[e.entity]?.damage ?: return
        }
    }

    @SubscribeEvent
    fun e(e: EntityDeathEvent) {
        map.remove(e.entity)
    }

    override val types: Array<AttributeType>
        get() = arrayOf(AttributeType.ATTACK)

    @SubscribeEvent(ignoreCancelled = true)
    fun e(e: EntityDamageEvent) {
        if (e.isPost && e.damageMemory[chance] == true) {
            val damage = Coerce.toDouble(e.damageMemory[damage])
            val resistance = Coerce.toDouble(e.damageMemory[resistance]) / 100
            val result = damage + damage * resistance
            val times = Coerce.toDouble(e.damageMemory[times])
            if (result >= 0) {
                map[e.damageMemory.injured] = Data(e.damageMemory.attacker,times, result)
                e.damageMemory.addDamage(Fire,result)
            }
            e.damageMemory.injured.fireTicks = Coerce.toInteger(times * 20)
        }

    }

    val chance = object : Attribute.Entry() {

        override val type: Attribute.Type
            get() = Attribute.Type.PERCENT

        override fun handler(memory: EventMemory, data: AttributeData.Data) {
            if (memory is DamageMemory && memory.isPointerAttack()) {
                memory[this] = random(data.get(this))
            }

        }

    }

    val times = object : Attribute.Entry() {

        override val type: Attribute.Type
            get() = Attribute.Type.SINGLE

        val default : Double
            get() = option?.getDouble("default") ?: 3.0

        override fun handler(memory: EventMemory, data: AttributeData.Data) {
            if (memory is DamageMemory && memory.isPointerAttack() && memory.labels[chance] == true) {
                memory[this] = data.get(this) + default
            }
        }
    }

    val damage = object : Attribute.Entry() {

        override val type: Attribute.Type
            get() = Attribute.Type.RANGE

        override fun handler(memory: EventMemory, data: AttributeData.Data) {
            if (memory is DamageMemory && memory.isPointerAttack() && memory.labels[chance] == true) {
                memory[this] = data.get(this)
            }
        }
    }

    val resistance = object : Attribute.Entry() {

        override val type: Attribute.Type
            get() = Attribute.Type.PERCENT

        override fun handler(memory: EventMemory, data: AttributeData.Data) {
            if (memory is DamageMemory && memory.isPointerInjured() && memory.labels[chance] == true) {
                memory[this] = data.get(this)
            }
        }

    }

    class Data(val source: LivingEntity,val times: Double,val damage: Double) {

        // 结束时间= 当前时间+持续时间
        // 持续时间单位为秒
        val endStamp = System.currentTimeMillis() + ( Coerce.toLong(times * 1000) )

        val isFinish : Boolean
            get() = System.currentTimeMillis() > endStamp

    }

}